import 'dart:io';
import 'package:todo_app/components/Overlay/main.dart';
import 'package:todo_app/constants/Screen.dart';
import 'package:todo_app/layout/Header.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future showH5({
  required BuildContext context,
  required String url,
  String? title,
  String? shareLink,
  bool showLoading = true,
  bool fullScreen = false,
  bool showShare = false,
  ValueChanged<InAppWebViewController>? onPageFinished,
  void Function(InAppWebViewController controller, LoadedResource resource)? onLoadResource,
  void Function(InAppWebViewController controller, int percent)? onProgressChanged,
  VoidCallback? onShare,
}) {
  return Navigator.of(context).push(MaterialPageRoute(
    builder: (_) {
      return H5WebView(
        url: url,
        title: title,
        shareLink: shareLink,
        showLoading: showLoading,
        fullScreen: fullScreen,
        showShare: showShare,
        onShare: onShare,
        onPageFinished: onPageFinished,
        onLoadResource: onLoadResource,
        onProgressChanged: onProgressChanged,
      );
    }
  ));
}

class H5WebView extends StatefulWidget {
  final String? url;
  final String? title;
  final String? shareLink;
  final bool fullScreen;
  final bool shareVisible;
  final VoidCallback? onShare;
  final bool showLoading;
  final bool showShare;
  final ValueChanged<InAppWebViewController>? onPageFinished;
  final void Function(InAppWebViewController controller, LoadedResource resource)? onLoadResource;
  final void Function(InAppWebViewController controller, int percent)? onProgressChanged;

  const H5WebView({
    Key? key, 
    this.onPageFinished, 
    this.onLoadResource, 
    this.showLoading = false, 
    this.shareVisible = false, 
    this.onShare,
    this.url, 
    this.shareLink,
    this.title,
    this.showShare = false,
    this.fullScreen = false,
    this.onProgressChanged
  }) : super(key: key);

  @override
  _H5WebViewState createState() => _H5WebViewState();
}

class _H5WebViewState extends State<H5WebView> {
  String? title;
  String? loadStatus;
  WebViewLoadingController? loadingController;

  @override
  void initState() { 
    super.initState();
    loadingController = WebViewLoadingController();
    if(widget.showLoading == true) {
      loadingController!.loading();
    }
  }

  @override
  void dispose() { 
    if(loadingController != null) {
      loadingController!.dispose();
    }
    super.dispose();
  }

  buildWebView() {
    return InAppWebView(
        initialUrlRequest: URLRequest(
          url: Uri.parse(widget.url!),
        ),
        initialOptions: InAppWebViewGroupOptions(
          crossPlatform: InAppWebViewOptions(
            mediaPlaybackRequiresUserGesture: false,
            javaScriptEnabled: true,
            useOnLoadResource: true,
            useShouldOverrideUrlLoading: true,
            transparentBackground: true,
            // userAgent: Platform.isIOS ?
            //   "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 DsBridge/1.0.0" :
            //   "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Mobile Safari/537.36 DsBridge/1.0.0"
          ),
          ios: IOSInAppWebViewOptions(
            allowsInlineMediaPlayback: true,
            allowsBackForwardNavigationGestures: false,
          ),
          android: AndroidInAppWebViewOptions(
            useHybridComposition: false,
            // allowContentAccess: true,
            // allowFileAccess: true,
            // networkAvailable: true,
            // useHybridComposition: true,
          ),
        ),
        gestureRecognizers: [
            Factory<OneSequenceGestureRecognizer>(
                () => EagerGestureRecognizer()),
        ].toSet(),
        androidOnPermissionRequest: (InAppWebViewController controller,
          String origin,
          List<String> resources) async {
            return PermissionRequestResponse(
              action: PermissionRequestResponseAction.GRANT,
              resources: resources
            );
        },
        onLoadError: (InAppWebViewController controller, Uri? url, int code, String message) {
          print(message);
          loadingController?.loadError();
        },
        onLoadHttpError: (InAppWebViewController controller, Uri? url, int statusCode, String description) {
          loadingController?.loadError();
        },
        onLoadStart: (InAppWebViewController controller, Uri? url) {
          print('Page started loading: $url');
        },
        onLoadStop: (InAppWebViewController controller, Uri? uri) async {
          var url = uri.toString();
          if(url == "about:blank" || url == "") return;
          // await controller.clearCache();
          loadingController?.loaded();
          if(widget.onPageFinished != null) {
            widget.onPageFinished!(controller);
          }
          title = await controller.getTitle();
          print('Page finished loading: $url');
        },
        onConsoleMessage: (InAppWebViewController controller, ConsoleMessage consoleMessage) {
          print("consoleMessage.message:${consoleMessage}");
          // controller.addJavaScriptHandler(handlerName: "Toast", callback: (message){
          //   print(message);
          // });
        },
        onLoadResource: (InAppWebViewController controller, LoadedResource resource) async {
          print(resource.url);
          if(widget.onLoadResource != null) {
            widget.onLoadResource!(controller, resource);
          }
          if(Platform.isIOS) {
            int? percent = await controller.getProgress();
            loadingController?.progress(percent);
          }
        },
        onProgressChanged: (InAppWebViewController controller, int _) async {
          if(widget.onProgressChanged != null) {
            widget.onProgressChanged!(controller, _);
          }
          if(!Platform.isIOS) {
            loadingController?.progress(_);
          } else {
            bool isLoading = await controller.isLoading();
            if(isLoading) {
              int? percent = await controller.getProgress();
              loadingController?.progress(percent);
            } else {
              loadingController?.loaded();
            }
          }
        }
    );
  }

  @override
  Widget build(BuildContext context) {
    Widget content = buildWebView();

    if(loadingController?.loadStatus == "loading") {
      content = Stack(
        children: [
          Container(
            width: Screen.width,
            child:  content,
          ),
          WebViewLoading(
            controller: loadingController!,
          ),
          Platform.isIOS ?
          Container(
            width: Screen.sizeByDesign(16),
            color: Colors.transparent
          ) : null
        ].where((element) => element != null).map<Widget>((e)=> e!).toList()
      );
    } else if(Platform.isIOS) {
      content = Stack(
        children: [
          Container(
            width: Screen.width,
            child:  content,
          ),
          Container(
            width: Screen.sizeByDesign(16),
            color: Colors.transparent
          )
        ]
      );
    }

    return Scaffold(
      appBar: Header(
        title: widget.title ?? ""
      ),
      body: content
    );
  }
}

class WebViewLoadingController extends ChangeNotifier {
  String? loadStatus;
  int? percent;

  int checkPercentCount = 0;

  loading() {
    loadStatus = "loading";
    percent = 0;
    notifyListeners();
  }

  progress(p) {
    if(loadStatus == "loading") {
      if(percent! >= 100) {
        loaded();
        return;
      }
      if(p == percent) checkPercentCount += 1;
      else checkPercentCount = 0;
      if(checkPercentCount >= 1)  {
        loadError();
        return;
      }
      percent = p;
      notifyListeners();
    }
  }

  loaded() {
    loadStatus = "loaded";
    notifyListeners();
  }

  loadError() {
    loadStatus = "error";
     notifyListeners();
  }
}


class WebViewLoading extends StatefulWidget {

  final WebViewLoadingController controller;

  WebViewLoading({ Key? key, required this.controller }) : super(key: key);

  @override
  _WebViewLoadingState createState() => _WebViewLoadingState();
}

class _WebViewLoadingState extends State<WebViewLoading> {

  @override
  void initState() {
    widget.controller.addListener(() {
      setState(() {});
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: Column(
        children: [
          Container(
            child:  widget.controller.loadStatus == "loading" ? LinearProgressIndicator(
              backgroundColor: Colors.transparent,
              value: widget.controller.percent!.toDouble(),
              minHeight: Screen.sizeByDesign(2)
            ) : null
          ),
          Expanded(
            child: Container(
              alignment: Alignment.center,
              child: widget.controller.loadStatus == "loading" ?  OverlayLoading(
                title: widget.controller.percent == 0 ? "加载中..." : "已加载${widget.controller.percent}%",
              ) : null,
            )
          )
        ]
      )
    );
  }
}